#pragma once

#ifndef _WINDOWS_
#include <windows.h>
#endif

#include <stdexcept>
#include <stdlib.h>
#include <range.h>
#include <pointers.h>



template <typename _Char>
struct  _other_char
{
};

template <>
struct  _other_char<char>
{
    typedef wchar_t Type;
};

template <>
struct  _other_char<wchar_t>
{
    typedef char Type;
};

static inline int cmp_void(const void* _1, const void* _2) throw()
{
    return ((_1 == _2)? 0 
            : ((_1 < _2) ? -1
            : 1 ));
}

template <typename _Ty = char>
struct CType
{
    typedef _Ty _char_t;

    static inline bool _isdigit(_char_t ch_)  throw()
    {
        return ToBool(::isdigit(ch_));
    }
    static inline bool _isxdigit(_char_t ch_)  throw()
    {
        return ToBool(::isxdigit(ch_));
    }
    static inline bool _isalpha(_char_t ch_) throw()
    {
        return ToBool(::isalpha(ch_));
    }
    static inline bool _isalnum(_char_t ch_) throw()
    {
        return ToBool(::isalnum(ch_));
    }
    static inline bool _isupper(_char_t ch_) throw()
    {
        return ToBool(::isupper(ch_));
    }
    static inline bool _islower(_char_t ch_) throw()
    {
        return ToBool(::islower(ch_));
    }
    static inline _char_t toupper(_char_t ch_) throw()
    {
        return (_char_t)::toupper(ch_);
    }
    static inline _char_t tolower(_char_t ch_) throw()
    {
        return  (_char_t)::tolower(ch_);
    }
    static inline bool _isspace(_char_t ch_) throw()
    {
        return ToBool(::isspace(ch_));
    }
    static inline bool _ispunct(_char_t ch_) throw()
    {
        return ToBool(::ispunct(ch_));
    }
    static inline bool _isascii(_char_t ch_) throw()
    {
        return ToBool(::isascii(ch_));
    }
    static inline bool _iscntrl(_char_t ch_) throw()
    {
        return ToBool(::iscntrl(ch_));
    }
    static inline bool _iscsym(_char_t ch_) throw()
    {
        return ToBool(__iscsym(ch_));
    }
    static inline bool _iscsymf(_char_t ch_) throw()
    {
        return ToBool(__iscsymf(ch_));
    }

};

template <>
struct CType<wchar_t> 
{
    typedef wchar_t _char_t;

    static inline bool _isdigit(_char_t ch_) throw()
    {
        return ToBool(::iswdigit(ch_));
    }
    static inline bool _isxdigit(_char_t ch_) throw()
    {
        return ToBool(::iswxdigit(ch_));
    }
    static inline bool _isalpha(_char_t ch_) throw()
    {
        return ToBool(::iswalpha(ch_));
    }
    static inline bool _isalnum(_char_t ch_) throw()
    {
        return ToBool(::iswalnum(ch_));
    }
    static inline bool _isupper(_char_t ch_) throw()
    {
        return ToBool(::iswupper(ch_));
    }
    static inline bool _islower(_char_t ch_) throw()
    {
        return ToBool(::iswlower(ch_));
    }
    static inline _char_t toupper(_char_t ch_) throw()
    {
        return (_char_t)::towupper(ch_);
    }
    static inline _char_t tolower(_char_t ch_) throw()
    {
        return  (_char_t)::towlower(ch_);
    }
    static inline bool _isspace(_char_t ch_) throw()
    {
        return ToBool(::iswspace(ch_));
    }
    static inline bool _ispunct(_char_t ch_) throw()
    {
        return ToBool(::iswpunct(ch_));
    }
    static inline bool _isascii(_char_t ch_) throw()
    {
        return ToBool(::iswascii(ch_));
    }
    static inline bool _iscntrl(_char_t ch_) throw()
    {
        return ToBool(::iswcntrl(ch_));
    }
    static inline bool _iscsym(_char_t ch_) throw()
    {
        return ToBool(__iswcsym(ch_));
    }
    static inline bool _iscsymf(_char_t ch_) throw()
    {
        return ToBool(__iswcsymf(ch_));
    }
};

#ifndef CP_ACP
#define CP_ACP 0
#endif

template <typename _Char>
struct  ChTraits_base
{
    static const unsigned int   CodePage = CP_ACP;

    typedef _Char   _Elem;
    typedef typename _other_char<_Char>::Type   _OtherElem;
	typedef _Elem char_type;
	typedef int int_type;
	typedef size_t size_type;
	typedef ptrdiff_t difference_type;

    typedef CType<_Elem>    ctype;

    typedef _Elem*  pointer;
    typedef const _Elem* const_pointer;

    typedef pointer iterator;
    typedef const_pointer   const_iterator;

    typedef range<pointer>  ptr_range;
    typedef range<const_pointer>  cptr_range;


    typedef _Elem&  reference;
    typedef const _Elem&    const_reference;

    typedef _OtherElem*  other_pointer;
    typedef const _OtherElem* other_const_pointer;
    typedef _OtherElem&  other_reference;
    typedef const _OtherElem&    other_const_reference;

    static const _Elem null = _Char(0);

    static inline const_pointer get_null_ptr() throw()
    {
        static _Elem _null[1] = {null};
        return _null;
    }

    static inline size_t  distance(const_pointer _1, const_pointer _2) throw()
    {
        return (((_1 && _2) && (_2 >= _1)) ? (_2 - _1) : no_value);
    }

    static inline bool _isdigit(_Elem ch_)  throw()
    {
        return ctype::_isdigit(ch_);
    }
    static inline bool _isxdigit(_Elem ch_)  throw()
    {
        return ctype::_isxdigit(ch_);
    }
    static inline bool _isalpha(_Elem ch_) throw()
    {
        return ctype::_isalpha(ch_);
    }
    static inline bool _isalnum(_Elem ch_) throw()
    {
        return ctype::_isalnum(ch_);
    }
    static inline bool _isupper(_Elem ch_) throw()
    {
        return ctype::_isupper(ch_);
    }
    static inline bool _islower(_Elem ch_) throw()
    {
        return ctype::_islower(ch_);
    }
    static inline _Elem toupper(_Elem ch_) throw()
    {
        return ctype::toupper(ch_);
    }
    static inline _Elem tolower(_Elem ch_) throw()
    {
        return  ctype::tolower(ch_);
    }
    static inline bool _isspace(_Elem ch_) throw()
    {
        return ctype::_isspace(ch_);
    }
    static inline bool _ispunct(_Elem ch_) throw()
    {
        return ctype::_ispunct(ch_);
    }
    static inline bool _isascii(_Elem ch_) throw()
    {
        return ctype::_isascii(ch_);
    }
    static inline bool _iscntrl(_Elem ch_) throw()
    {
        return ctype::_iscntrl(ch_);
    }
    static inline bool _iscsym(_Elem ch_) throw()
    {
        return ctype::_iscsym(ch_);
    }
    static inline bool _iscsymf(_Elem ch_) throw()
    {
        return ctype::_iscsymf(ch_);
    }

    static inline int_type to_int_type(_Elem ch_) throw()
    {
        return int((unsigned)ch_);
    }

    static inline _Elem to_char_type(const int_type int_) throw()
    {
        return ((_Elem)int_);
    }

    static inline int cmp(_Elem _1, _Elem _2) throw()
    {
        return to_int_type(_1) - to_int_type(_2);
    }

    static inline int cmpi(_Elem _1, _Elem _2) throw()
    {
        return to_int_type(tolower(_1)) - to_int_type(tolower(_2));
    }

    static inline pointer fill(pointer p_, size_t count_, _Elem val_) throw()
    {
        if (p_)
            while(count_--)
                *p_++ = val_;
        return p_;
    }

    static int cmp(const_pointer _1, const_pointer _2) throw()
    {
        if (_1 != _2)// are not the same
        {
            if (_1 && _2) // both non-null
            {
                while(*_1 && *_2)
                {
                    int ret = cmp(*_1, *_2);
                    if (ret)
                        return ret;
                    ++_1, ++_2;
                }
                return cmp(*_1, *_2);
            }
            return (!_1)? -1 : 1;
        }
        return 0;
    }

    static int cmpn(const_pointer _1, const_pointer _2, size_t cch_) throw()
    {
        if (_1 != _2 && cch_ > 0)// are not the same
        {
            if (_1 && _2) // both non-null
            {
                while(cch_-- && *_1 && *_2)
                {
                    int ret = cmp(*_1, *_2);
                    if (ret)
                        return ret;
                    ++_1, ++_2;
                }
                return 0;
            }
            return (!_1)? -1 : 1;
        }
        return 0;
    }

    static int cmpi(const_pointer _1, const_pointer _2) throw()
    {
        if (_1 != _2)// are not the same
        {
            if (_1 && _2) // both non-null
            {
                while(*_1 && *_2)
                {
                    int ret = cmpi(*_1, *_2);
                    if (ret)
                        return ret;
                    ++_1, ++_2;
                }
                return cmp(*_1, *_2);
            }
            return (!_1)? -1 : 1;
        }
        return 0;
    }

    static int cmpni(const_pointer _1, const_pointer _2, size_t cch_) throw()
    {
        if (_1 != _2 && cch_ > 0)// are not the same
        {
            if (_1 && _2) // both non-null
            {
                while(cch_-- && *_1 && *_2)
                {
                    int ret = cmpi(*_1, *_2);
                    if (ret)
                        return ret;
                    ++_1, ++_2;
                }
                return 0;
            }
            return (!_1)? -1 : 1;
        }
        return 0;
    }

};

template <typename _Char>
struct  ChTraits : public ChTraits_base<_Char>
{
};

template <>
struct ChTraits<char> : public ChTraits_base<char> 
{
    typedef ChTraits<_OtherElem>    _OtherTraits;

    static inline size_t length(const_pointer p_) throw()
    {
        return (size_t) strlen(p_);
    }

    static inline size_t base_length(other_const_pointer p_, size_t length_ = no_value) throw()
    {
		// Returns required buffer length in XCHARs
		return (size_t)
            ::WideCharToMultiByte( CodePage, 0, p_, (int)length_, NULL, 0, NULL, NULL )
            - ((length_ == no_value)?1:0)
            ;
    }

    static inline size_t convert(pointer to_, size_t length_to_, other_const_pointer from_, size_t length_from_ = no_value) throw()
    {
		// nLen is in XCHARs
		return (size_t)
            ::WideCharToMultiByte( CodePage, 0, from_, (int)length_from_, to_, (int)length_to_, NULL, NULL );
    }

    static inline errno_t copy(pointer to_, size_t size_to_,  const_pointer from_, size_t size_from_) throw()
    {
        return (to_ == from_)? 0 : ::memcpy_s(to_, size_to_, from_, size_from_);
    }

    static inline size_t formatted_length(const_pointer format_, va_list args_) throw()
    {
        if (!format_ || !*format_)
            return 0;
        return (size_t)::_vscprintf(format_, args_);
    }

    static inline size_t formatV(pointer buff_, size_t buff_size_, const_pointer format_, va_list args_) throw()
    {
        if (!format_ || !*format_)
            return 0;
        return (size_t)::vsnprintf_s(buff_, buff_size_, _TRUNCATE, format_, args_);
    }

    static inline size_t format(pointer buff_, size_t buff_size_, const_pointer format_, ...) throw()
    {
        va_list args;
        va_start(args, format_);
        size_t result = (buff_ == NULL)? formatted_length(format_, args) : formatV(buff_, buff_size_, format_, args);
        va_end(args);
        return result;
    }

	static inline const_pointer find(_In_count_(cch_) const_pointer ptr_, size_t cch_, _Elem ch_) throw()
	{
		return ((const_pointer)::memchr(ptr_, ch_, cch_));
	}

    static inline pointer move(_Out_cap_(dest_size_) pointer dest_, size_t dest_size_, _In_count_(cch_) const_pointer src_, size_t cch_) throw()
    {
        ::memmove_s(dest_, dest_size_, src_, cch_);
        return dest_;
    }
};

template <>
struct ChTraits<wchar_t> : public ChTraits_base<wchar_t> 
{
    typedef ChTraits<_OtherElem>    _OtherTraits;

    static inline size_t length(const_pointer p_) throw()
    {
        return (size_t) ::wcslen(p_);
    }

    static inline size_t base_length(other_const_pointer p_, size_t length_ = no_value) throw()
    {
		// Returns required buffer length in XCHARs
		return (size_t)
            ::MultiByteToWideChar( CodePage, 0, p_, (int)length_, NULL, 0)
            - ((length_ == no_value)?1:0)
            ;
    }

    static inline size_t convert(pointer to_, size_t length_to_, other_const_pointer from_, size_t length_from_ = no_value) throw()
    {
		// nLen is in XCHARs
		return (size_t)
            ::MultiByteToWideChar( CodePage, 0, from_, (int)length_from_, to_, (int)length_to_);
    }

    static inline errno_t copy(pointer to_, size_t size_to_,  const_pointer from_, size_t size_from_) throw()
    {
        return (to_ == from_)? 0 : ::wmemcpy_s(to_, size_to_, from_, size_from_);
    }

    static inline size_t formatted_length(const_pointer format_, va_list args_) throw()
    {
        if (!format_ || !*format_)
            return 0;
        return (size_t)::_vscwprintf(format_, args_);
    }

    static inline size_t formatV(pointer buff_, size_t buff_size_, const_pointer format_, va_list args_) throw()
    {
        if (!format_ || !*format_)
            return 0;
        return (size_t)::_vsnwprintf_s(buff_, buff_size_, _TRUNCATE, format_, args_);
    }

    static inline size_t format(pointer buff_, size_t buff_size_, const_pointer format_, ...) throw()
    {
        va_list args;
        va_start(args, format_);
        size_t result = (buff_ == NULL)? formatted_length(format_, args) : formatV(buff_, buff_size_, format_, args);
        va_end(args);
        return result;
    }

	static const_pointer find(_In_count_(cch_) const_pointer ptr_, size_t cch_, const_reference ch_) throw()
	{
		return ((const_pointer)::wmemchr(ptr_, ch_, cch_));
	}

    static inline pointer move(_Out_cap_(dest_size_) pointer dest_, size_t dest_size_, _In_count_(cch_) const_pointer src_, size_t cch_) throw()
    {
        ::wmemmove_s(dest_, dest_size_, src_, cch_);
        return dest_;
    }
};

template <typename _Char>
class print_buffer;

template <typename _Char>
struct TypeConv; 

template <typename _Char>
class   print_buffer : public marus::refcounted< print_buffer<_Char> >
{
public:
    typedef ChTraits<_Char>    _Traits;
    typedef typename _Traits::pointer pointer;
    typedef typename _Traits::const_pointer const_pointer;
    typedef TypeConv<_Char>     _Conv;
    typedef print_buffer        _Myt;
    typedef range<const_pointer>    _Range;

    // pure virtuals to implement in derived classes
    //
protected:
    // increases internal counter by length_.
    // returns new size
    // NOTE: this method is protected by intent and must stay protected 
    // for it directly changes object's internal state
    virtual size_t   advance(size_t length_) = 0;

public:
    // returns const pointer to internal buffer at position at_
    virtual const_pointer   data(size_t at_) const = 0;

    // returns current size of stored data 
    virtual size_t  size() const = 0;

    // ensures size_ characters are available in buffer(reallocates buffer when not) 
    // returns pointer to the beginning of free area 
    virtual pointer get(size_t size_) = 0;

    // appends size_ characters of _data and increments current size
    // when size_ equals no_value ((size_t)-1), calculates the length of data_ on the fly
    // Note: _data may be the pointer previously obtained by get(size) method.
    // Implementor should avoid copying daata to itself
    virtual size_t  append(const_pointer data_, size_t size_) = 0;

    // clears internal buffers. after reset() method size() must return 0.
    virtual void    reset() = 0;

    // utilities
    bool    empty() const
    {
        return 0 == size();
    }

    _Range  range(size_t start_, size_t length_) const
    {
        return (_Range(data(start_), data(start_+length_)));
    }

    size_t  append_range(const _Range& range_)
    {
        return append(range_.first, range_.length());
    }
    // modifiers
    template <typename T> 
    _Myt & operator <<(const T& val_)
    {
        return put(val_);
    }

    // fundamental types
    _Myt&   put(bool val_)
    {
        _Char data[] =  {(val_? '1' : '0'), 0};
        _Conv::append_string(*this, data, 1);
        return *this;
    }
    _Myt& put(signed char val_)
    {
        static const _Char fmt[] = {'%', 'c', 0};
        advance(_Traits::format(get(4), 4, fmt, val_));
        return *this;
    }
    _Myt& put(char val_)
    {
        static const _Char fmt[] = {'%', 'h', 'c', 0};
        advance(_Traits::format(get(4), 4, fmt, val_));
        return *this;
    }
    _Myt& put(unsigned char val_)
    {
        return put((unsigned)val_);
    }
    _Myt& put(wchar_t val_)
    {
        static const _Char fmt[] = {'%', 'w', 'c', 0};
        advance(_Traits::format(get(6), 6, fmt, val_));
        return *this;
    }
    _Myt& put(short val_)
    {
        _Conv::to_string(*this, val_);
        return *this;
    }
    _Myt& put(unsigned short val_)
    {
        _Conv::to_string(*this, val_);
        return *this;
    }
    _Myt& put(int val_)
    {
        _Conv::to_string(*this, val_);
        return *this;
    }
    _Myt& put(unsigned int val_)
    {
        _Conv::to_string(*this, val_);
        return *this;
    }
    _Myt& put(long val_)
    {
        _Conv::to_string(*this, val_);
        return *this;
    }
    _Myt& put(unsigned long val_)
    {
        _Conv::to_string(*this, val_);
        return *this;
    }
    _Myt& put(__int64 val_)
    {
        _Conv::to_string(*this, val_);
        return *this;
    }
    _Myt& put(unsigned __int64 val_)
    {
        _Conv::to_string(*this, val_);
        return *this;
    }
    _Myt& put(float val_)
    {
        _Conv::to_string(*this, val_, 6);
        return *this;
    }
    _Myt& put(double val_)
    {
        _Conv::to_string(*this, val_, 6);
        return *this;
    }
    _Myt& put(long double val_)
    {
        return put((double)val_);
    }
    _Myt& put(const char* val_, size_t length_ = no_value)
    {
        _Conv::append_string(*this, val_, length_);
        return *this;
    }
    _Myt& put(const wchar_t* val_, size_t length_ = no_value)
    {
        _Conv::append_string(*this, val_, length_);
        return *this;
    }
    _Myt& put(const void* val_)
    {
        _Conv::append_pointer(*this, val_);
        return *this;
    }

    template<typename _Char>
    size_t copy(print_buffer<_Char>& out_) const
    {
        return TypeConv<_Char>::append_string(out_, data(0), size());
    }
    size_t copy(_Myt& out_) const
    {
        return _Conv::append_string(out_, data(), size());
    }
};

template <typename _Char>
struct TypeConv_base 
{
    typedef ChTraits<_Char> _Traits;
    typedef ChTraits<typename _Traits::_OtherElem> _OtherTraits;

    typedef typename _Traits::_Elem _Elem;
    typedef typename _Traits::pointer pointer;
    typedef typename _Traits::const_pointer const_pointer;
    typedef typename _Traits::other_const_pointer other_const_pointer;
    typedef print_buffer<_Char> print_buffer;

    static inline void hex(unsigned char c_, _Elem out_[2])
    {
        static const _Elem __hex[] = {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F'};
        out_[1] = __hex[c_ & 0x0F];
        out_[0] = __hex[c_>>4];
    }

    static size_t append_pointer(print_buffer& pbuf_, const void* ptr_)
    {
        const size_t precision = 2*sizeof(void*);
        _Elem*   tmp(pbuf_.get(precision+1)); //[precision] = {'0'};
        _Traits::fill(tmp, precision, _Elem('0'));
        if (ptr_)
        {
            union {
                unsigned char _bytes[sizeof(void*)];
                const void* _value;
            } mix;
            mix._value = ptr_;
            for(size_t i = 0; i < sizeof(void*); ++i)
            {
                unsigned char c = mix._bytes[i];
                if (c != 0)
                {
                    hex(c, &tmp[(sizeof(void*)-i-1)<<1]);
                }
            }
        }
        return pbuf_.append(tmp, precision);
    }

    static inline size_t append_string(print_buffer& pbuf_, const_pointer str_, size_t size_ = no_value)
    {
        return pbuf_.append(str_, (size_ == no_value)?_Traits::length(str_) : size_);
    }

    static inline size_t append_string(print_buffer& pbuf_, other_const_pointer str_, size_t size_ = no_value)
    {
        size_t len = (size_ == no_value)?_OtherTraits::length(str_) : size_;
        size_t needed = _Traits::base_length(str_, len);
        pointer p = pbuf_.get(needed+1);
        if (p == NULL)
            return no_value;
        return pbuf_.append(p, _Traits::convert(p, needed, str_, len));
    }

};

template <typename _Char>
struct TypeConv : public TypeConv_base<_Char>
{};

template <>
struct TypeConv<char> : public TypeConv_base<char>
{
    static size_t to_string(print_buffer& pbuf_, long val_, int radix_ = 10)
    {
        pointer tmp(pbuf_.get(33));
        if (0 == ::_ltoa_s(val_, tmp, 33, radix_)) 
            return pbuf_.append(tmp, _Traits::length(tmp));
        return no_value;
    }

    static size_t to_string(print_buffer& pbuf_, unsigned long val_, int radix_ = 10)
    {
        pointer tmp(pbuf_.get(33));
        if (0 == ::_ultoa_s(val_, tmp, 33, radix_)) 
            return pbuf_.append(tmp, _Traits::length(tmp));
        return no_value;
    }

    static size_t to_string(print_buffer& pbuf_, __int64 val_, int radix_ = 10)
    {
        pointer tmp(pbuf_.get(65));
        if (0 == ::_i64toa_s(val_, tmp, 65, radix_)) 
            return pbuf_.append(tmp, _Traits::length(tmp));
        return no_value;
    }

    static size_t to_string(print_buffer& pbuf_, unsigned __int64 val_, int radix_ = 10)
    {
        pointer tmp(pbuf_.get(65));
        if (0 == ::_i64toa_s(val_, tmp, 65, radix_)) 
            return pbuf_.append(tmp, _Traits::length(tmp));
        return no_value;
    }

    static inline size_t to_string(print_buffer& pbuf_, short val_, int radix_ = 10)
    {
        return to_string(pbuf_, (long)val_, radix_);
    }

    static inline size_t to_string(print_buffer& pbuf_, unsigned short val_, int radix_ = 10)
    {
        return to_string(pbuf_, (unsigned long)val_, radix_);
    }

    static inline size_t to_string(print_buffer& pbuf_, int val_, int radix_ = 10)
    {
        return to_string(pbuf_, (long)val_, radix_);
    }

    static inline size_t to_string(print_buffer& pbuf_, unsigned int val_, int radix_ = 10)
    {
        return to_string(pbuf_, (unsigned long)val_, radix_);
    }

    static size_t to_string(print_buffer& pbuf_, double val_, int digits_ = 15)
    {
        char tmp[_CVTBUFSIZE+1];
        if (0 == ::_gcvt_s(tmp, _CVTBUFSIZE+1, val_, _STD max(1, _STD min(digits_, _CVTBUFSIZE))))
        {
            return pbuf_.append(tmp, _Traits::length(tmp));
        }
        return no_value;
    }

    static inline size_t to_string(print_buffer& pbuf_, float val_, int digits_ = 15)
    {
        return to_string(pbuf_, (double)val_, digits_);
    }

};

template <>
struct TypeConv<wchar_t> : public TypeConv_base<wchar_t>
{
    static size_t to_string(print_buffer& pbuf_, long val_, int radix_ = 10)
    {
        pointer tmp(pbuf_.get(33));
        if (0 == ::_ltow_s(val_, tmp, 33, radix_)) 
            return pbuf_.append(tmp, _Traits::length(tmp));
        return no_value;
    }

    static size_t to_string(print_buffer& pbuf_, unsigned long val_, int radix_ = 10)
    {
        pointer tmp(pbuf_.get(33));
        if (0 == ::_ultow_s(val_, tmp, 33, radix_)) 
            return pbuf_.append(tmp, _Traits::length(tmp));
        return no_value;
    }

    static size_t to_string(print_buffer& pbuf_, __int64 val_, int radix_ = 10)
    {
        pointer tmp(pbuf_.get(65));
        if (0 == ::_i64tow_s(val_, tmp, 65, radix_)) 
            return pbuf_.append(tmp, _Traits::length(tmp));
        return no_value;
    }

    static size_t to_string(print_buffer& pbuf_, unsigned __int64 val_, int radix_ = 10)
    {
        pointer tmp(pbuf_.get(65));
        if (0 == ::_i64tow_s(val_, tmp, 65, radix_)) 
            return pbuf_.append(tmp, _Traits::length(tmp));
        return no_value;
    }

    static inline size_t to_string(print_buffer& pbuf_, short val_, int radix_ = 10)
    {
        return to_string(pbuf_, (long)val_, radix_);
    }

    static inline size_t to_string(print_buffer& pbuf_, unsigned short val_, int radix_ = 10)
    {
        return to_string(pbuf_, (unsigned long)val_, radix_);
    }

    static inline size_t to_string(print_buffer& pbuf_, int val_, int radix_ = 10)
    {
        return to_string(pbuf_, (long)val_, radix_);
    }

    static inline size_t to_string(print_buffer& pbuf_, unsigned int val_, int radix_ = 10)
    {
        return to_string(pbuf_, (unsigned long)val_, radix_);
    }

    static size_t to_string(print_buffer& pbuf_, double val_, int digits_ = 15)
    {
        char tmp[_CVTBUFSIZE+1];
        if (0 == ::_gcvt_s(tmp, _CVTBUFSIZE+1, val_, _STD max(1, _STD min(digits_, _CVTBUFSIZE))))
            return append_string(pbuf_, tmp);
        return no_value;
    }

    static inline size_t to_string(print_buffer& pbuf_, float val_, int digits_ = 15)
    {
        return to_string(pbuf_, (double)val_, digits_);
    }

};

